#include <stdio.h>
#ifdef USEMPI
#include <mpi.h>
#endif
#ifdef USEOMP
#include "parallel.h"
#endif
long int numsteps = 2E9;
double step;
int main_ (int argc, char ** argv)
{   
    int myid, num_process;
    double pi, sum = 0.0;
    double r_sum =0.0;   //for mpi only
    step = 1.0 / (double)numsteps;  
    printf("step = %.20lf\n", step);  
#ifdef USEMPI
    MPI_Status status;      
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &num_process);
#endif    
#ifdef USEOMP 
    #pragma omp parallel for reduction(+:sum) 
#endif
    for (int i = myid + 1; i <= numsteps; i = i + num_process){   
        double x = ((double)i - 0.5) * step;
        sum += 4.0 / (1.0 + x * x);
    }
#ifdef USEOMP 
    printf("step = %.20lf, pi = %.20lf\n",step, sum * step);
#endif
    sum = sum * step;
    r_sum = sum;
#ifdef USEMPI
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Reduce(&sum, &r_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD) ; 
    MPI_Barrier(MPI_COMM_WORLD);
#endif

    if(myid == 0) {  
        pi = r_sum;
        printf("pi is %.20f\n",pi);
    }
    
#ifdef USEMPI  
    MPI_Finalize();
#endif 
        return 0;
}



int main(int argc, char **argv){

#ifdef USEOMP
    for(int i = 0; i < 9; i++){
        double start, end; 
        int thread = threads[i]; 
        omp_set_num_threads(thread);
        printf("use omp ");
        start = omp_get_wtime(); 
        main_(argc, argv);
        end = omp_get_wtime(); 
        printf("thread %d Work took %f seconds\n",thread, end - start);
    }
#endif

#ifdef USEMPI

    main_(argc, argv);    

#endif
}


